home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / infoserv / gopher / Unix / xvgopher / v0.5beta / xvgopher.shar.01.Z / xvgopher.shar.01 / Connection.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-25  |  8.4 KB  |  426 lines

  1. //
  2. // Connection.cc
  3. //
  4. // (c) Copyright 1993, San Diego State University -- College of Sciences
  5. //       (See the COPYRIGHT file for more Copyright information)
  6. //
  7. // Implementation of the Connection class
  8. //
  9.  
  10. #include "Connection.h"
  11. #include <errno.h>
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #include <netinet/in.h>
  16. #include <sys/ioctl.h>
  17. #include <unistd.h>
  18.  
  19.  
  20. Connection::Connection()
  21. {
  22.     sock = -1;
  23.     pos = pos_max = 0;
  24. }
  25.  
  26.  
  27. //*************************************************************************
  28. // Connection::Connection(int socket)
  29. // PURPOSE:
  30. //   Create a connection from just a socket.
  31. // PARAMETERS:
  32. //   int socket:  obvious!!!!
  33. //
  34. Connection::Connection(int socket)
  35. {
  36.     sock = socket;
  37.  
  38.     int length = sizeof(server);
  39.     if (getpeername(socket, (struct sockaddr *)&server, &length) < 0)
  40.     {
  41.         perror("getpeername");
  42.     }
  43.     pos = pos_max = 0;
  44. }
  45.  
  46.  
  47. Connection::~Connection()
  48. {
  49.     this->close();
  50. }
  51.  
  52.  
  53. int Connection::open(int priv)
  54. {
  55.     if (priv)
  56.     {
  57.         int    aport = IPPORT_RESERVED - 1;
  58.  
  59.         sock = rresvport(&aport);
  60.     }
  61.     else
  62.         sock = socket(AF_INET, SOCK_STREAM, 0);
  63.  
  64.     if (sock == NOTOK)
  65.         return NOTOK;
  66.  
  67.     int    on = 1;
  68.     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
  69.     server.sin_family = AF_INET;
  70.  
  71.     pos = pos_max = 0;
  72.     return OK;
  73. }
  74.  
  75.  
  76. int Connection::close()
  77. {
  78.     if (sock >= 0)
  79.     {
  80.         int ret = ::close(sock);
  81.         sock = -1;
  82.         return ret;
  83.     }
  84.     return NOTOK;
  85. }
  86.  
  87.  
  88. int Connection::assign_port(int port)
  89. {
  90.     server.sin_port = htons(port);
  91.     return OK;
  92. }
  93.  
  94.  
  95. int Connection::assign_port(char *service)
  96. {
  97.     struct servent        *sp;
  98.  
  99.     sp = getservbyname(service, "tcp");
  100.     if (sp == NULL)
  101.     {
  102.         return NOTOK;
  103.     }
  104.     server.sin_port = sp->s_port;
  105.     return OK;
  106. }
  107.  
  108. int Connection::assign_server(dword addr)
  109. {
  110.     server.sin_addr.s_addr = addr;
  111.     return OK;
  112. }
  113.  
  114. int Connection::assign_server(char *name)
  115. {
  116.     struct hostent        *hp;
  117.  
  118.     hp = gethostbyname(name);
  119.     if (hp == NULL)
  120.     {
  121.         return NOTOK;
  122.     }
  123.     memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
  124.     return OK;
  125. }
  126.  
  127.  
  128. int Connection::connect()
  129. {
  130.     if (::connect(sock, (struct sockaddr *)&server, sizeof(server)) == NOTOK)
  131.     {
  132.         return NOTOK;
  133.     }
  134.     return OK;
  135. }
  136.  
  137.  
  138. int Connection::bind()
  139. {
  140.     if (::bind(sock, (struct sockaddr *)&server, sizeof(server)) == NOTOK)
  141.     {
  142.         return NOTOK;
  143.     }
  144.     return OK;
  145. }
  146.  
  147.  
  148. int Connection::get_port()
  149. {
  150.     int    length;
  151.  
  152.     if (getsockname(sock, (struct sockaddr *)&server, &length) == NOTOK)
  153.     {
  154.         return NOTOK;
  155.     }
  156.     return ntohs(server.sin_port);
  157. }
  158.  
  159.  
  160. int Connection::listen(int n)
  161. {
  162.     return ::listen(sock, n);
  163. }
  164.  
  165.  
  166. Connection *Connection::accept(int priv)
  167. {
  168.     int    newsock;
  169.  
  170.     while (TRUE)
  171.     {
  172.         newsock = ::accept(sock, (struct sockaddr *)0, (int *)0);
  173.         if (newsock == NOTOK && errno == EINTR)
  174.             continue;
  175.         break;
  176.     }
  177.     if (newsock == NOTOK)
  178.         return (Connection *)0;
  179.  
  180.     Connection    *newconnect = new Connection;
  181.     newconnect->sock = newsock;
  182.  
  183.     int length = sizeof(newconnect->server);
  184.     getpeername(newsock, (struct sockaddr *)&newconnect->server, &length);
  185.  
  186.     if (priv && newconnect->server.sin_port >= IPPORT_RESERVED)
  187.     {
  188.         delete newconnect;
  189.         return (Connection *)0;
  190.     }
  191.  
  192.     return newconnect;
  193. }
  194.  
  195.  
  196. //*************************************************************************
  197. // Connection *Connection::accept_privileged()
  198. // PURPOSE:
  199. //   Accept  in  incoming  connection  but  only  if  it  is  from a
  200. //   privileged port
  201. //
  202. Connection * Connection::accept_privileged()
  203. {
  204.     return accept(1);
  205. }
  206.  
  207.  
  208. //*************************************************************************
  209. // METHOD int Connection::write(char *buffer, int length)
  210. // PURPOSE:
  211. //   Write  <nbytes>  bytes  from  <buffer>  to file sock. This will
  212. //   take  care  of  problems where write will return without having
  213. //   written everything in the buffer.
  214. // PARAMETERS:
  215. //   char    *buffer:    The buffer to write.
  216. //   int    nbytes:        The number of bytes to write from <buffer>.
  217. // RETURN VALUE:
  218. //   Returns  number  of  bytes  actually  written.  If there was an
  219. //   error it returns -1.
  220. // SIDE EFFECTS:
  221. //   None
  222. // ASSUMPTIONS:
  223. //   None
  224. // FUNCTIONS USED:
  225. //   write()
  226. // ALGORYTHM:
  227. //   Stevens p. 279
  228. //
  229. int Connection::write(char *buffer, int length)
  230. {
  231.     int    nleft, nwritten;
  232.  
  233.     nleft = length;
  234.     while (nleft > 0)
  235.     {
  236.         nwritten = ::write(sock, buffer, nleft);
  237.         if (nwritten <= 0)
  238.             return nwritten;
  239.         nleft -= nwritten;
  240.         buffer += nwritten;
  241.     }
  242.     return length - nleft;
  243. }
  244.  
  245.  
  246. //*************************************************************************
  247. // METHOD int Connection::write(char *buffer)
  248. // PURPOSE:
  249. //   This is identical to the other write except that the length of the
  250. //   buffer is not passed.  The buffer is assumed to be NULL terminated.
  251. // PARAMETERS:
  252. //   char    *buffer:    The buffer to write.
  253. // RETURN VALUE:
  254. //   Returns  number  of  bytes  actually  written.  If there was an
  255. //   error it returns -1.
  256. //
  257. int Connection::write(char *buffer)
  258. {
  259.     return write(buffer, strlen(buffer));
  260. }
  261.  
  262.  
  263. //*************************************************************************
  264. // int Connection::read(char *buffer, int length)
  265. // PURPOSE:
  266. //   Read  <length>  bytes  from the current TCP connection. We will
  267. //   not  return  until  we  have  all  the  data we are waiting for
  268. //   unless there was an error
  269. // PARAMETERS:
  270. //   char *buffer:    Buffer to read the data into
  271. //   int length:    The number of bytes to read into the buffer
  272. // RETURN VALUE:
  273. //   The actual number of bytes read.  NOTOK if an error occured.
  274. // ASSUMPTIONS:
  275. //   The connection has been previously established.
  276. // FUNCTIONS USED:
  277. //   read()
  278. // ALGORYTHM:
  279. //   Stevens p. 279
  280. //
  281. int Connection::read(char *buffer, int length)
  282. {
  283.     int    nleft, nread;
  284.  
  285.     nleft = length;
  286.     while (nleft > 0)
  287.     {
  288.         nread = ::read(sock, buffer, nleft);
  289.         if (nread < 0 && errno == EINTR)
  290.             continue;
  291.         else if (nread < 0)
  292.         {
  293.             perror("read");
  294.             return nread;
  295.         }
  296.         else if (nread == 0)
  297.             return -1;            // End of file/stream
  298.  
  299.         nleft -= nread;
  300.         buffer += nread;
  301.     }
  302.     return length - nleft;
  303. }
  304.  
  305.  
  306. //***************************************************************************
  307. // char *Connection::read_line(char *buffer, int maxlength)
  308. // PURPOSE:
  309. //   Read a line of text, terminated by CR and or LF.
  310. //
  311. char *Connection::read_line(char *buffer, int maxlength)
  312. {
  313.     while (maxlength > 0)
  314.     {
  315.         int    ch = get_char();
  316.         if (ch < 0)
  317.             return (char *) 0;
  318.         else if (ch == '\r')
  319.             continue;
  320.         else if (ch == '\n')
  321.             break;
  322.         else
  323.         {
  324.             *buffer++ = ch;
  325.             maxlength--;
  326.         }
  327.     }
  328.     *buffer = '\0';
  329.     return buffer;
  330. }
  331.  
  332.  
  333. //*************************************************************************
  334. // int Connection::read_partial(char *buffer, int maxlength)
  335. // PURPOSE:
  336. //   Read  at  most  <maxlength>  from  the  current TCP connection.
  337. //   This  is  equivalent  to  the  workings  of the standard read()
  338. //   system call
  339. // PARAMETERS:
  340. //   char *buffer:    Buffer to read the data into
  341. //   int maxlength:    Maximum number of bytes to read into the buffer
  342. // RETURN VALUE:
  343. //   The actual number of bytes read in.
  344. // ASSUMPTIONS:
  345. //   The connection has been previously established.
  346. // FUNCTIONS USED:
  347. //   read()
  348. //
  349. int Connection::read_partial(char *buffer, int maxlength)
  350. {
  351.     return ::read(sock, buffer, maxlength);
  352. }
  353.  
  354.  
  355. //*************************************************************************
  356. // int Connection::bytes_available()
  357. // PURPOSE:
  358. //   Check  to  see  how  many bytes can be read from the connection
  359. //   currently
  360. // RETURN VALUE:
  361. //   The number of bytes available.
  362. //
  363. int Connection::bytes_available()
  364. {
  365.     int    count = -1;
  366.  
  367.     ioctl(sock, FIONREAD, (char *) &count);
  368.  
  369.     return count;
  370. }
  371.  
  372.  
  373. //*************************************************************************
  374. // char * Connection::socket_as_string()
  375. // PURPOSE:
  376. //   Return  the  numeric  ASCII  equivalent  of  the socket number.
  377. //   This is needed to pass the socket to another program
  378. //
  379. char * Connection::socket_as_string()
  380. {
  381.     char    buffer[20];
  382.  
  383.     sprintf(buffer, "%d", sock);
  384.     return strdup(buffer);
  385. }
  386.  
  387.  
  388. //*************************************************************************
  389. // int Connection::get_socket()
  390. // PURPOSE:
  391. //   Return the current socket number
  392. //
  393. int Connection::get_socket()
  394. {
  395.     return sock;
  396. }
  397.  
  398.  
  399. //*************************************************************************
  400. // int Connection::isopen()
  401. // PURPOSE:
  402. //   Return true if the connection is open
  403. //
  404. int Connection::isopen()
  405. {
  406.     return sock >= 0;
  407. }
  408.  
  409.  
  410. //*************************************************************************
  411. // int Connection::get_char()
  412. //
  413. int Connection::get_char()
  414. {
  415.     if (pos >= pos_max)
  416.     {
  417.         pos_max = read_partial(buffer, BUFFER_SIZE);
  418.         pos = 0;
  419.         if (pos_max <= 0)
  420.             return -1;
  421.     }
  422.     return buffer[pos++];
  423. }
  424.  
  425.  
  426.